import { LogEntry, LogLevel } from '../types';

export class LogFormatter {
  private static readonly LOG_LEVEL_COLORS = {
    ERROR: '\x1b[31m', // 红色
    WARN: '\x1b[33m',  // 黄色
    INFO: '\x1b[36m',  // 青色
    DEBUG: '\x1b[90m'  // 灰色
  };

  private static readonly RESET_COLOR = '\x1b[0m';

  /**
   * 格式化日志条目为字符串
   * 格式: [时间戳] [级别] [来源] 消息内容
   */
  static formatLogEntry(entry: LogEntry): string {
    const timestamp = this.formatTimestamp(entry.timestamp);
    const level = this.formatLevel(entry.level);
    const source = this.formatSource(entry.source);
    const message = this.formatMessage(entry.message, entry.data);

    return `[${timestamp}] [${level}] [${source}] ${message}`;
  }

  /**
   * 格式化带颜色的日志条目（用于控制台输出）
   */
  static formatColoredLogEntry(entry: LogEntry): string {
    const timestamp = this.formatTimestamp(entry.timestamp);
    const level = this.formatColoredLevel(entry.level);
    const source = this.formatSource(entry.source);
    const message = this.formatMessage(entry.message, entry.data);

    return `[${timestamp}] [${level}] [${source}] ${message}`;
  }

  /**
   * 格式化时间戳为ISO 8601格式
   */
  private static formatTimestamp(timestamp: Date): string {
    return timestamp.toISOString();
  }

  /**
   * 格式化日志级别
   */
  private static formatLevel(level: LogLevel): string {
    return level.padEnd(5, ' ');
  }

  /**
   * 格式化带颜色的日志级别
   */
  private static formatColoredLevel(level: LogLevel): string {
    const color = this.LOG_LEVEL_COLORS[level];
    const formattedLevel = level.padEnd(5, ' ');
    return `${color}${formattedLevel}${this.RESET_COLOR}`;
  }

  /**
   * 格式化来源信息
   */
  private static formatSource(source: string): string {
    // 限制来源字符串长度，避免日志行过长
    const maxLength = 20;
    if (source.length > maxLength) {
      return source.substring(0, maxLength - 3) + '...';
    }
    return source.padEnd(maxLength, ' ');
  }

  /**
   * 格式化消息内容
   */
  private static formatMessage(message: string, data?: any): string {
    let formattedMessage = message;

    // 如果有附加数据，将其序列化并添加到消息后面
    if (data !== undefined) {
      try {
        const dataString = typeof data === 'string' 
          ? data 
          : JSON.stringify(data, null, 0);
        formattedMessage += ` | Data: ${dataString}`;
      } catch (error) {
        formattedMessage += ` | Data: [Unserializable Object]`;
      }
    }

    return formattedMessage;
  }

  /**
   * 生成日志文件名
   * 格式: cli-YYYY-MM-DD-HH.log
   */
  static generateLogFileName(date: Date = new Date()): string {
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    const hour = String(date.getHours()).padStart(2, '0');

    return `cli-${year}-${month}-${day}-${hour}.log`;
  }

  /**
   * 解析日志文件名中的时间信息
   */
  static parseLogFileName(fileName: string): Date | null {
    const match = fileName.match(/cli-(\d{4})-(\d{2})-(\d{2})-(\d{2})\.log$/);
    if (!match) {
      return null;
    }

    const [, year, month, day, hour] = match;
    return new Date(
      parseInt(year, 10),
      parseInt(month, 10) - 1, // 月份从0开始
      parseInt(day, 10),
      parseInt(hour, 10)
    );
  }

  /**
   * 验证日志级别
   */
  static isValidLogLevel(level: string): level is LogLevel {
    return ['ERROR', 'WARN', 'INFO', 'DEBUG'].includes(level);
  }

  /**
   * 比较日志级别优先级
   * 返回值: 负数表示level1优先级高于level2，正数表示相反，0表示相等
   */
  static compareLogLevel(level1: LogLevel, level2: LogLevel): number {
    const levels = { ERROR: 0, WARN: 1, INFO: 2, DEBUG: 3 };
    return levels[level1] - levels[level2];
  }

  /**
   * 检查是否应该记录指定级别的日志
   */
  static shouldLog(entryLevel: LogLevel, configLevel: LogLevel): boolean {
    return this.compareLogLevel(entryLevel, configLevel) <= 0;
  }

  /**
   * 清理消息内容，移除潜在的控制字符
   */
  static sanitizeMessage(message: string): string {
    // 移除ANSI转义序列
    return message.replace(/\x1b\[[0-9;]*m/g, '');
  }

  /**
   * 创建结构化的错误日志条目
   */
  static createErrorLogEntry(
    source: string,
    message: string,
    error?: Error
  ): LogEntry {
    const errorData = error ? {
      name: error.name,
      message: error.message,
      stack: error.stack
    } : undefined;

    return {
      timestamp: new Date(),
      level: 'ERROR',
      source,
      message: this.sanitizeMessage(message),
      data: errorData
    };
  }

  /**
   * 创建警告日志条目
   */
  static createWarnLogEntry(
    source: string,
    message: string,
    data?: any
  ): LogEntry {
    return {
      timestamp: new Date(),
      level: 'WARN',
      source,
      message: this.sanitizeMessage(message),
      data
    };
  }

  /**
   * 创建信息日志条目
   */
  static createInfoLogEntry(
    source: string,
    message: string,
    data?: any
  ): LogEntry {
    return {
      timestamp: new Date(),
      level: 'INFO',
      source,
      message: this.sanitizeMessage(message),
      data
    };
  }

  /**
   * 创建调试日志条目
   */
  static createDebugLogEntry(
    source: string,
    message: string,
    data?: any
  ): LogEntry {
    return {
      timestamp: new Date(),
      level: 'DEBUG',
      source,
      message: this.sanitizeMessage(message),
      data
    };
  }
}